/* =========================================
 *           语音识别子服务实现 
 * =========================================*/
#pragma once
#include "speech_recognition.pb.h"
#include "asr.hpp"
#include "etcd.hpp"
#include <brpc/closure_guard.h>
#include <brpc/controller.h>
#include <brpc/server.h>
#include <memory>

namespace speech {

class SpeechServiceImpl;
class SpeechServer;
class SpeechServerBuilder;
using SpeechServiceImplPtr = std::shared_ptr<SpeechServiceImpl>;
using SpeechServerPtr = std::shared_ptr<SpeechServer>;
using SpeechServerBuilderPtr = std::shared_ptr<SpeechServerBuilder>;

class SpeechServiceImpl : public im_proto::SpeechService 
{
public:
    SpeechServiceImpl(const shared::infra::ASRClientPtr& asrClient) : asrClient_(asrClient) {}
    ~SpeechServiceImpl(){}

    void SpeechRecognition(google::protobuf::RpcController* controller,
                        const ::im_proto::SpeechRecognitionReq* request,
                        ::im_proto::SpeechRecognitionRsp* response,
                        ::google::protobuf::Closure* done) 
    {
        brpc::ClosureGuard rpc_guard(done);
        // 调用语音sdk模块
        std::string err;
        std::string res = asrClient_->recognize(request->speech_content(), err);
        if (res.empty()) {
            LOG_ERROR("{} 语音识别失败: {}", request->request_id(), err);
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err);
            return;
        }
        // 构建响应体
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_recognition_result(res);
    }
private:
    shared::infra::ASRClientPtr asrClient_;
};


class SpeechServer
{
public: 
    SpeechServer(const shared::infra::ASRClientPtr& asrClient, 
        const shared::infra::RegistrantPtr& registerClient, 
        const std::shared_ptr<brpc::Server>& rpcServer)
        : asrClient_(asrClient), registerClient_(registerClient), rpcServer_(rpcServer) {}
    ~SpeechServer() {}
    void start() { rpcServer_->RunUntilAskedToQuit(); }
private:
    shared::infra::ASRClientPtr asrClient_;
    shared::infra::RegistrantPtr registerClient_;
    std::shared_ptr<brpc::Server> rpcServer_;
};

class SpeechServerBuilder
{
public:
    // 构造语音识别客户端对象
    void makeAsrObject(const std::string& appId, const std::string& apiKey, const std::string& secretKey)
    {
        asrClient_ = make_shared<shared::infra::ASRClient>(appId, apiKey, secretKey);
    }
    // 构造服务注册客户端对象
    void makeRegistrantObject(const std::string& host, const std::string& serviceName, const std::string& accessHost)
    {
        registerClient_ = make_shared<shared::infra::Registrant>(host);
        registerClient_->registry(serviceName, accessHost);
    }
    // 构造RPC服务器对象
    void makeRpcServer(uint16_t port, int32_t timeout, uint8_t numThreads)
    {
        if (!asrClient_) {
            LOG_ERROR("还未初始化语音识别模块！");
            abort();
        }
        rpcServer_ = make_shared<brpc::Server>();
        // 向rpc注册服务
        // SpeechServiceImplPtr speechServiceImpl = std::make_shared<SpeechServiceImpl>(asrClient_);
        SpeechServiceImpl* speechServiceImpl = new SpeechServiceImpl(asrClient_);
        if(rpcServer_->AddService(speechServiceImpl, brpc::ServiceOwnership::SERVER_OWNS_SERVICE) == -1) {
            LOG_ERROR("添加Rpc服务失败!");
            abort();
        }
        // 启动服务器
        brpc::ServerOptions options;    
        options.idle_timeout_sec = timeout;  
        options.num_threads = numThreads;        
        if(rpcServer_->Start(port, &options) == -1) {
            LOG_ERROR("Rpc服务启动失败!");
            abort();
        }
    }
    SpeechServerPtr build()
    {
       if (!asrClient_) {
            LOG_ERROR("还未初始化语音识别模块!");
            abort();
        }
        if (!registerClient_) {
            LOG_ERROR("还未初始化服务注册模块!");
            abort();
        }
        if (!rpcServer_) {
            LOG_ERROR("还未初始化RPC服务器模块!");
            abort();
        }
        return std::make_shared<SpeechServer>(asrClient_, registerClient_, rpcServer_);
    }
private:
    shared::infra::ASRClientPtr asrClient_;
    shared::infra::RegistrantPtr registerClient_;
    std::shared_ptr<brpc::Server> rpcServer_;
};

}